/**
 @file ctc_ax_port.c

 @date 2020-06-15

 @version v1.0

---file comments----
*/

#include "ctc_asw_common.h"
#include "ctc_asw_port.h"
#include "ctc_vlan.h"
#include "ctc_acl.h"
#include "ctc_asw_interrupt.h"
#include "ctc_asw_vlan.h"
#include "ctc_asw_qos.h"
#include "ctc_asw_chip.h"
#include "asw/include/drv_api.h"
/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/

/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/
#define CTC_ASW_PORT_LINK_PCS_MAX_IDX  64
/***************************************************************
 *
 *  Functions
 *
 ***************************************************************/
#define ______INTERNAL______
STATIC int32
_ctc_asw_port_pcs_link_isr(uint8 lchip, uint32 intr, void* p_data)
{
    int32   ret = 0;
    uint8 index = 0;
    uint32* p_value = NULL;
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;
    ctc_port_link_status_t port_link_status;
    uint8 pcs_port_mapping[CTC_ASW_PORT_LINK_PCS_MAX_IDX/2] = {20, 21, 22, 23, 16, 17, 18, 19, 12, 13, 14, 15, 8, 9, 10, 11,
                                                               27, 26, 25, 24, 20, 16, 12, 8, 27, 26, 25, 24, 20, 16, 12, 8};

    sal_memset(&port_link_status, 0, sizeof(port_link_status));
    CTC_ERROR_RETURN(_ctc_asw_intr_get_event_func(lchip, CTC_EVENT_PORT_LINK_CHANGE, &cb))
    if (NULL == cb)
    {
        return CTC_E_NONE;
    }

    p_value = (uint32*)p_data;
    for(index=0; index<CTC_ASW_PORT_LINK_PCS_MAX_IDX; index+=2)
    { 
        if (CTC_IS_BIT_SET(p_value[index>>5], index%32)
        || CTC_IS_BIT_SET(p_value[(index+1)>>5], (index+1)%32))
        {
            sal_memset(&port_link_status, 0, sizeof(port_link_status));
            port_link_status.gport = pcs_port_mapping[index/2];
            cb(lchip, &port_link_status);
        }
    }

    return ret;
}

#define ______INTERNAL_API_____
int32
_ctc_asw_mac_get_property(uint8 lchip, uint32 gport, ctc_port_property_t port_prop, uint32* p_value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t ds;

    switch (port_prop)
    {
        case CTC_PORT_PROP_MAC_EN:
            cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacRxCtrl(V, portEn_f, &ds);
            break;
        case CTC_PORT_PROP_AUTO_NEG_EN:
            ret = _ctc_asw_datapath_get_auto_neg_enable(lchip, gport, p_value);
            break;
        case CTC_PORT_PROP_AUTO_NEG_MODE:
            {
                ctc_port_auto_neg_mode_t mode;
                ret = _ctc_asw_datapath_get_auto_neg_mode(lchip, gport, &mode);
                *p_value = mode;
            }
            break;
        case CTC_PORT_PROP_SPEED:
            {
                uint32 speed_sel = 0;

                cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
                ret = DRV_IOCTL(lchip, gport, cmd, &ds);
                speed_sel = GetMacTxCtrl(V, speedSel_f, &ds);
                *p_value = (2==speed_sel)?CTC_PORT_SPEED_1G:((1==speed_sel)?CTC_PORT_SPEED_100M:CTC_PORT_SPEED_10M);
            }
            break;

        case CTC_PORT_PROP_LINK_UP:
            cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            if (!GetMacRxCtrl(V, portEn_f, &ds))
            {
                *p_value = 0;
                return CTC_E_NONE;
            }
            if (CTC_E_NONE == _ctc_asw_peri_get_phy_register_exist(lchip, gport))
            {
                CTC_ERROR_RETURN(_ctc_asw_peri_get_phy_prop(lchip, gport, CTC_PORT_PROP_LINK_UP, (void*)p_value));
                return CTC_E_NONE;
            }
            ret = _ctc_asw_datapath_get_link_up(lchip, gport, p_value);
            break;

        case CTC_PORT_PROP_HALF_DUPLEX:
            cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacTxCtrl(V, duplexMode_f, &ds);
            break;

        case CTC_PORT_PROP_EEE_EN:
            cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacTxCtrl(V, eeeEn_f, &ds);
            break;

        case CTC_PORT_PROP_PREAMBLE:
            cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacTxCtrl(V, preSel_f, &ds)?8:4;
            break;

        case CTC_PORT_PROP_IPG:
            cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacTxCtrl(V, ipgSel_f, &ds)+8;
            break;

        case CTC_PORT_PROP_LEARNING_EN:     /**< Set learning enable/disable on port */
            cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacLkupCtrl(V,newEnable_f,&ds);
            break;

        case CTC_PORT_PROP_CHK_CRC_EN:
            cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacRxCtrl(V, crcCheckEn_f, &ds);
            break;

        case CTC_PORT_PROP_STRIP_CRC_EN:
            cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacRxCtrl(V, crcStripEn_f, &ds);
            break;

        case CTC_PORT_PROP_APPEND_CRC_EN:
            cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacTxCtrl(V, crcInsertEn_f, &ds);
            break;
        case CTC_PORT_PROP_UNIDIR_EN:
            ret = _ctc_asw_datapath_get_unidir_en(lchip, gport, p_value);
            break;
        case CTC_PORT_PROP_LINK_INTRRUPT_EN:
            ret = _ctc_asw_datapath_get_pcs_link_isr_en(lchip, gport, p_value);
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }

    return ret;
}

int32
_ctc_asw_mac_set_property(uint8 lchip, uint32 gport, ctc_port_property_t port_prop, uint32 value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t ds;

    switch (port_prop)
    {
    case CTC_PORT_PROP_MAC_EN:
        cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacRxCtrl(V, portEn_f, &ds, value?1:0);
        cmd = DRV_IOW(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);

        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret?ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacTxCtrl(V, portEn_f, &ds, value?1:0);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret?ret:DRV_IOCTL(lchip, gport, cmd, &ds);

        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret?ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        SetEgressPort(V, portDown_f, &ds, value?0:1);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret?ret:DRV_IOCTL(lchip, gport, cmd, &ds);

        ret = ret?ret:_ctc_asw_datapath_set_pcs_en(lchip, gport, value);
        break;
    case CTC_PORT_PROP_AUTO_NEG_EN:
        value = (value) ? TRUE : FALSE;
        ret = _ctc_asw_datapath_set_auto_neg_enable(lchip, gport, value);
        break;
    case CTC_PORT_PROP_AUTO_NEG_MODE:
        ret = _ctc_asw_datapath_set_auto_neg_mode(lchip, gport, value);
        break;
    case CTC_PORT_PROP_SPEED:
        {
            uint32 speed_sel = 0;

            CTC_MAX_VALUE_CHECK(value, CTC_PORT_SPEED_10M);
            cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            speed_sel = (CTC_PORT_SPEED_1G==value)?2:((CTC_PORT_SPEED_100M==value)?1:0);
            SetMacTxCtrl(V, speedSel_f, &ds, speed_sel);
            cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
            ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        }
        break;

    case CTC_PORT_PROP_HALF_DUPLEX:
        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacTxCtrl(V, duplexMode_f, &ds, value?1:0);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_EEE_EN:
        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacTxCtrl(V, eeeEn_f, &ds, value?1:0);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_PREAMBLE:
        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        if ((value !=4) && (value != 8))
        {
            ret = CTC_E_INVALID_PARAM;
        }
        SetMacTxCtrl(V, preSel_f, &ds, (8 == value)?1:0);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_IPG:
        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        if (value > 15 || value < 8)
        {
            ret = CTC_E_INVALID_PARAM;
        }
        SetMacTxCtrl(V, ipgSel_f, &ds, value-8);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        break;
     case CTC_PORT_PROP_CHK_CRC_EN:
        cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacRxCtrl(V, crcCheckEn_f, &ds, value?1:0);
        cmd = DRV_IOW(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_STRIP_CRC_EN:
        cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacRxCtrl(V, crcStripEn_f, &ds, value?1:0);
        cmd = DRV_IOW(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_APPEND_CRC_EN:
        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacTxCtrl(V, crcInsertEn_f, &ds, value?1:0);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        break;
    case CTC_PORT_PROP_UNIDIR_EN:
        ret = _ctc_asw_datapath_set_unidir_en(lchip, gport, value);
        break;
    case CTC_PORT_PROP_LINK_INTRRUPT_EN:
        ret = _ctc_asw_datapath_set_pcs_link_isr_en(lchip, gport, value);
        break;
    default:
        ret = CTC_E_NOT_SUPPORT;
        break;
    }

    return ret;
}

int32
_ctc_asw_port_set_internal_property(uint8 lchip, uint32 gport, ctc_asw_port_internal_property_t port_prop, uint32 value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    IngressPort_m ingress_port;
    PortStcBaseCtrl_m Port_stc_base_ctrl;

    switch (port_prop)
    {
        case CTC_PORT_INT_PROP_INGRESS_POLICER_PTR:
            cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ingress_port);
            SetIngressPort(V, policeIndex_f, &ingress_port, value);
            SetIngressPort(V, counterIndex_f, &ingress_port, value+CTC_ASW_MAX_STATS_ID+1);
            cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
            ret = ret ? ret : (DRV_IOCTL(lchip, gport, cmd, &ingress_port));
            break;
        case CTC_PORT_INT_PROP_STMCTL_EN:
            cmd = DRV_IOR(PortStcBaseCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &Port_stc_base_ctrl);
            SetPortStcBaseCtrl(V, portStcEn_f, &Port_stc_base_ctrl, value);
            cmd = DRV_IOW(PortStcBaseCtrl_t, DRV_ENTRY_FLAG);
            ret = ret ? ret : (DRV_IOCTL(lchip, gport, cmd, &Port_stc_base_ctrl));
            break;
        case CTC_PORT_INT_PROP_STMCTL_OFFSET:
            cmd = DRV_IOR(PortStcBaseCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &Port_stc_base_ctrl);
            SetPortStcBaseCtrl(V, stcBaseIndex_f, &Port_stc_base_ctrl, value);
            cmd = DRV_IOW(PortStcBaseCtrl_t, DRV_ENTRY_FLAG);
            ret = ret ? ret : (DRV_IOCTL(lchip, gport, cmd, &Port_stc_base_ctrl));
            break;
        case CTC_PORT_INT_PROP_SMAC_GRP_ID:
            cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ingress_port);
            SetIngressPort(V,spmacGroupid_f,&ingress_port,value);
            cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
            ret = ret ? ret : (DRV_IOCTL(lchip, gport, cmd, &ingress_port));
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }
    return ret;
}

int32
_ctc_asw_port_get_internal_property(uint8 lchip, uint32 gport, ctc_asw_port_internal_property_t port_prop, uint32* p_value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    IngressPort_m ingress_port;
    PortStcBaseCtrl_m Port_stc_base_ctrl;
    switch (port_prop)
    {
        case CTC_PORT_INT_PROP_INGRESS_POLICER_PTR:
            cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ingress_port);
            *p_value = GetIngressPort(V,policeIndex_f,&ingress_port);
            break;
        case CTC_PORT_INT_PROP_STMCTL_EN:
            cmd = DRV_IOR(PortStcBaseCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &Port_stc_base_ctrl);
            *p_value = GetPortStcBaseCtrl(V,portStcEn_f,&Port_stc_base_ctrl);
            break;
        case CTC_PORT_INT_PROP_STMCTL_OFFSET:
            cmd = DRV_IOR(PortStcBaseCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &Port_stc_base_ctrl);
            *p_value = GetPortStcBaseCtrl(V,stcBaseIndex_f,&Port_stc_base_ctrl);
            break;
        case CTC_PORT_INT_PROP_SMAC_GRP_ID:
            cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ingress_port);
            *p_value = GetIngressPort(V,spmacGroupid_f,&ingress_port);
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }
    return ret;
}

#define ______API______
int32
ctc_asw_port_set_stag_tpid_index(uint8 lchip, uint32 gport, ctc_direction_t dir, uint8 index)
{
    uint32 cmd = 0;
    ds_t ds;
    int32  ret = 0;

    CTC_MAX_GPORT_CHECK(gport);
    if (index >= 4)
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_API_LOCK(lchip);
    if ((dir == CTC_EGRESS) || (dir == CTC_BOTH_DIRECTION))
    {
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetEgressPort(V, stpidIndex_f, &ds, index);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, gport, cmd, &ds));
    }
    if ((dir == CTC_INGRESS) || (dir == CTC_BOTH_DIRECTION))
    {
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetIngressPort(V, stpidEnable_f, &ds, 1 << index);
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, gport, cmd, &ds));
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_get_stag_tpid_index(uint8 lchip, uint32 gport, ctc_direction_t dir, uint8* index)
{
    uint32 field_val = 0;
    ds_t ds;
    uint32 cmd = 0;
    int32  ret = 0;

    CTC_MAX_VALUE_CHECK(dir, CTC_EGRESS);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    if (dir == CTC_EGRESS)
    {
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        field_val = GetEgressPort(V, stpidIndex_f, &ds);
        *index = field_val;
    }
    else if (dir == CTC_INGRESS)
    {
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        field_val = GetIngressPort(V, stpidEnable_f, &ds);
        if (field_val == 1)
        {
            *index = 0;
        }
        else if (field_val == 2)
        {
            *index = 1;
        }
        else if (field_val == 4)
        {
            *index = 2;
        }
        else
        {
            *index = 3;
        }
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_set_isolation(uint8 lchip, ctc_port_isolation_t* p_port_isolation)
{
    int32  ret = 0;
    uint32 cmd = 0;
    IngressPort_m igrport;

    CTC_PTR_VALID_CHECK(p_port_isolation);
    CTC_MAX_GPORT_CHECK(p_port_isolation->gport);
    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, p_port_isolation->gport, cmd, &igrport);
    switch (p_port_isolation->isolation_pkt_type)
    {
        case CTC_PORT_ISOLATION_ALL:
            SetIngressPort(V, egressPortMask_f, &igrport, p_port_isolation->pbm[0]);
            break;
        case CTC_PORT_ISOLATION_UNKNOW_MCAST:
            SetIngressPort(V, mlfMask_f, &igrport, p_port_isolation->pbm[0]);
            break;
        case CTC_PORT_ISOLATION_UNKNOW_UCAST:
            SetIngressPort(V, ulfMask_f, &igrport, p_port_isolation->pbm[0]);
            break;
        case CTC_PORT_ISOLATION_BCAST:
            SetIngressPort(V, bcMask_f, &igrport, p_port_isolation->pbm[0]);
            break;
        default:
            ret = CTC_E_INVALID_PARAM;
            break;
    }
    cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : (DRV_IOCTL(lchip, p_port_isolation->gport, cmd, &igrport));
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_get_isolation(uint8 lchip, ctc_port_isolation_t* p_port_isolation)
{
    uint32 cmd = 0;
    IngressPort_m igrport;
    uint32 field_val = 0;
    int32  ret = 0;

    CTC_PTR_VALID_CHECK(p_port_isolation);
    CTC_MAX_GPORT_CHECK(p_port_isolation->gport);
    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, p_port_isolation->gport, cmd, &igrport);
    switch (p_port_isolation->isolation_pkt_type)
    {
        case CTC_PORT_ISOLATION_ALL:
            field_val = GetIngressPort(V, egressPortMask_f, &igrport);
            break;
        case CTC_PORT_ISOLATION_KNOW_MCAST:
            field_val = GetIngressPort(V, mlfMask_f, &igrport);
            break;
        case CTC_PORT_ISOLATION_KNOW_UCAST:
            field_val = GetIngressPort(V, ulfMask_f, &igrport);
            break;
        case CTC_PORT_ISOLATION_BCAST:
            field_val = GetIngressPort(V, bcMask_f, &igrport);
            break;
        default:
            ret = CTC_E_INVALID_PARAM;
            break;
    }
    p_port_isolation->pbm[0] = field_val;
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_set_property(uint8 lchip, uint32 gport, ctc_port_property_t port_prop, uint32 value)
{
    ds_t ds;
    uint32 cmd = 0;
    int32  ret = 0;
    uint32  field = 0;
    uint32  domain_id = 0;
    uint32 vlan_id = 0;

    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    switch (port_prop)
    {
    case CTC_PORT_PROP_MAC_EN:
    case CTC_PORT_PROP_AUTO_NEG_EN:
    case CTC_PORT_PROP_AUTO_NEG_MODE:
    case CTC_PORT_PROP_SPEED:
    case CTC_PORT_PROP_HALF_DUPLEX:
    case CTC_PORT_PROP_EEE_EN:
    case CTC_PORT_PROP_PREAMBLE:
    case CTC_PORT_PROP_IPG:
    case CTC_PORT_PROP_CHK_CRC_EN:
    case CTC_PORT_PROP_STRIP_CRC_EN:
    case CTC_PORT_PROP_APPEND_CRC_EN:
    case CTC_PORT_PROP_UNIDIR_EN:
    case CTC_PORT_PROP_LINK_INTRRUPT_EN:
        ret = _ctc_asw_mac_set_property(lchip, gport, port_prop, value);
        break;

    case CTC_PORT_PROP_VLAN_CTL:
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        switch (value)
        {
            case  CTC_VLANCTL_ALLOW_ALL_PACKETS:
                SetIngressPort(V, no1pPkt_f, &ds, 0);
                SetIngressPort(V, noTagPkt_f, &ds, 0);
                SetIngressPort(V, noUntagPkt_f, &ds, 0);
                break;
            case CTC_VLANCTL_DROP_ALL_UNTAGGED:
                SetIngressPort(V, no1pPkt_f, &ds, 0);
                SetIngressPort(V, noTagPkt_f, &ds, 0);
                SetIngressPort(V, noUntagPkt_f, &ds, 1);
                break;
            case CTC_VLANCTL_DROP_ALL_TAGGED:
                SetIngressPort(V, no1pPkt_f, &ds, 1);
                SetIngressPort(V, noTagPkt_f, &ds, 1);
                SetIngressPort(V, noUntagPkt_f, &ds, 0);
                break;
            case CTC_VLANCTL_DROP_ALL :
                SetIngressPort(V, no1pPkt_f, &ds, 1);
                SetIngressPort(V, noTagPkt_f, &ds, 1);
                SetIngressPort(V, noUntagPkt_f, &ds, 1);
                break;
            default:
                ret = ret ? ret : CTC_E_INVALID_PARAM;
                break;
        }
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;
    case CTC_PORT_PROP_DEFAULT_VLAN:
        CTC_MAX_VALUE_CHECK_UNLOCK(value, CTC_ASW_MAX_VLAN);
        field = gport + CTC_VLAN_PORT_AD_BASE;
        cmd = DRV_IOR(IvmTable_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, field, cmd, &ds);

        vlan_id = GetIvmTable(V, svid_f, &ds);
        SetIvmTable(V, svid_f, &ds, value);
        cmd = DRV_IOW(IvmTable_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, field, cmd, &ds);

        cmd = DRV_IOR(EvtTable_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, vlan_id, cmd, &ds));
        domain_id = GetEvtTable(V, vlanUntagMap_f, &ds);
        CTC_BIT_UNSET(domain_id, gport);
        SetEvtTable(V, vlanUntagMap_f, &ds, domain_id);
        cmd = DRV_IOW(EvtTable_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, vlan_id, cmd, &ds));

        cmd = DRV_IOR(EvtTable_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, value, cmd, &ds));
        field = GetEvtTable(V, vlanUntagMap_f, &ds);
        CTC_BIT_SET(field, gport);
        SetEvtTable(V, vlanUntagMap_f, &ds, field);
        cmd = DRV_IOW(EvtTable_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, value, cmd, &ds));
        break;
    case CTC_PORT_PROP_VLAN_DOMAIN:
        CTC_MAX_VALUE_CHECK_UNLOCK(value, CTC_PORT_VLAN_DOMAIN_MAX);
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        if (CTC_PORT_VLAN_DOMAIN_SVLAN == value)
        {
            SetIngressPort(V, stpidEnable_f, &ds, 0x1);
        }
        else
        {
            SetIngressPort(V, stpidEnable_f, &ds, 0x0);
        }
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;
    case CTC_PORT_PROP_LEARNING_EN:     /**< Set learning enable/disable on port */
        field = (value) ? 1 : 0;
        cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        if (GetMacLkupCtrl(V,newLearnMode_f,&ds) == 1)
        {
            SetMacLkupCtrl(V, newsaToFifo_f, &ds,field);
        }
        SetMacLkupCtrl(V, newEnable_f, &ds, field);
        cmd = DRV_IOW(MacLkupCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_STATION_MOVE_ACTION:
        field = (value == CTC_PORT_STATION_MOVE_ACTION_TYPE_DISCARD_TOCPU) ? 1 : 0;
        cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacLkupCtrl(V, moveToFifo_f, &ds, field);
        field = (value != CTC_PORT_STATION_MOVE_ACTION_TYPE_FWD) ? 1 : 0;
        SetMacLkupCtrl(V, moveToDrop_f, &ds, field);
        cmd = DRV_IOW(MacLkupCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_QOS_POLICY:
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        domain_id = GetIngressPort(V, priIndex_f, &ds);
        if (value == CTC_QOS_TRUST_STAG_COS)
        {
            value = 2;
        }
        else if (value == CTC_QOS_TRUST_DSCP)
        {
            value = 3;
        }
        else if (value == CTC_QOS_TRUST_PORT)
        {
            value = 0;
        }
        else
        {
            CTC_API_UNLOCK(lchip);
            return CTC_E_INVALID_PARAM;
        }
        SetIngressPort(V, remarkScosMode_f, &ds, 0);
        SetIngressPort(V, remarkDscpMode_f, &ds, 0);
        SetIngressPort(V, trustPriMode_f, &ds, value);
        domain_id = (value  == 3) ? (domain_id | 0x8) : (domain_id & 0x7);
        SetIngressPort(V, priIndex_f, &ds, domain_id);
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_REPLACE_STAG_COS:
        field = (value) ? 2 : 0;
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        domain_id = GetEgressPort(V, priIndex_f, &ds);
        domain_id = domain_id & 0x7;
        SetEgressPort(V, remarkScosMode_f, &ds, field);
        SetEgressPort(V, remarkDscpMode_f, &ds, 0);
        SetEgressPort(V, priIndex_f, &ds, domain_id);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_DSCP_SELECT_MODE:
        CTC_MAX_VALUE_CHECK_UNLOCK(value, MAX_CTC_DSCP_SELECT_MODE - 1);
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetEgressPort(V, remarkDscpMode_f, &ds, value);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_REPLACE_DSCP_EN:
        field = (value) ? 2 : 0;
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        domain_id = GetEgressPort(V, priIndex_f, &ds);
        domain_id = domain_id | 0x8;
        SetEgressPort(V, remarkDscpMode_f, &ds, field);
        SetEgressPort(V, remarkScosMode_f, &ds, 0);
        SetEgressPort(V, priIndex_f, &ds, domain_id);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_DEFAULT_DSCP:
        if (value > CTC_MAX_QOS_DSCP_VALUE)
        {
            CTC_API_UNLOCK(lchip);
            return CTC_E_INVALID_PARAM;
        }
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetEgressPort(V, remarkDscp_f, &ds, value);
        SetEgressPort(V, remarkDscpMode_f, &ds, 1);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_REPLACE_PCP_DEI:
        field = (value) ? 1 : 0;
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetEgressPort(V, remarkScosMode_f, &ds, value);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_DEFAULT_PCP:
        CTC_MAX_VALUE_CHECK_UNLOCK(value, 7);
        /*ingress*/
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        field = GetIngressPort(V, remarkScos_f, &ds);
        value = ((field & 0x1) | (value << 1));
        SetIngressPort(V, remarkScos_f, &ds, value);
        SetIngressPort(V, remarkScosMode_f, &ds, 1);
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        /*egress*/
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        field = GetEgressPort(V, remarkScos_f, &ds);
        value = ((field & 0x1) | (value << 1));
        SetEgressPort(V, remarkScos_f, &ds, value);
        SetEgressPort(V, remarkScosMode_f, &ds, 1);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_DEFAULT_DEI:
        CTC_MAX_VALUE_CHECK_UNLOCK(value, 1);
        /*ingress*/
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        field = GetIngressPort(V, remarkScos_f, &ds);
        value = ((field & 0xE) | value);
        SetIngressPort(V, remarkScos_f, &ds, value);
        SetIngressPort(V, remarkScosMode_f, &ds, 1);
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        /*egress*/
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        field = GetEgressPort(V, remarkScos_f, &ds);
        value = ((field & 0xE) | value);
        SetEgressPort(V, remarkScos_f, &ds, value);
        SetEgressPort(V, remarkScosMode_f, &ds, 1);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_MAX_FRAME_SIZE:
        CTC_MAX_VALUE_CHECK_UNLOCK(value, 16383);
        cmd = DRV_IOR(MaxFrameLen_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMaxFrameLen(V, len_f, &ds, value);
        cmd = DRV_IOW(MaxFrameLen_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_QOS_WRR_EN:
        field = (value) ? 1 : 0;
        cmd = DRV_IOR(SchPortMode_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetSchPortMode(V, wrrMode_f, &ds,field);
        cmd = DRV_IOW(SchPortMode_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_NEW_SA_DROP:
        field = (value) ? 1 : 0;
        cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetMacLkupCtrl(V, newEnable_f, &ds, (field ? 0:1));
        SetMacLkupCtrl(V, newsaToDrop_f, &ds, field);
        cmd = DRV_IOW(MacLkupCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_PRIORITY_TAG_EN:
        field = (value) ? 1 : 0;
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        SetIngressPort(V, no1pPkt_f, &ds, field?0:1);
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
        break;

    case CTC_PORT_PROP_PHY_INIT:
        ret = _ctc_asw_peri_set_phy_prop(lchip, gport, CTC_PORT_PROP_PHY_INIT, (void*)&value);
        break;
    case CTC_PORT_PROP_PHY_EN:
        {
            uint32 phy_id = CTC_CHIP_PHY_NULL_PHY_ID;
            _ctc_asw_peri_get_phy_id(lchip, gport, &phy_id);
            if ((CTC_E_NONE == _ctc_asw_peri_get_phy_register_exist(lchip, gport)) && (phy_id != CTC_CHIP_PHY_NULL_PHY_ID))
            {
                ret = _ctc_asw_peri_set_phy_prop(lchip, gport, CTC_PORT_PROP_PHY_EN, (void*)&value);
            }
            else
            {
                ret = _ctc_asw_mac_set_property(lchip, gport, CTC_PORT_PROP_MAC_EN, value);
            }
        }
        break;
    case CTC_PORT_PROP_PHY_DUPLEX:
    case CTC_PORT_PROP_PHY_MEDIUM:
    case CTC_PORT_PROP_PHY_LOOPBACK:
    case CTC_PORT_PROP_PHY_AUTO_NEG_EN:
    case CTC_PORT_PROP_PHY_SPEED:
        if (CTC_E_NONE == _ctc_asw_peri_get_phy_register_exist(lchip, gport))
        {
            ret = _ctc_asw_peri_set_phy_prop(lchip, gport, port_prop, (void*)&value);
        }
        else
        {
            ret = CTC_E_NOT_INIT;
        }
        break;
    default:
        ret = CTC_E_NOT_SUPPORT;
        break;
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_get_property(uint8 lchip, uint32 gport, ctc_port_property_t port_prop, uint32* p_value)
{
    ds_t ds;
    uint32  cmd = 0;
    int32   ret = 0;
    uint32  field = 0;
    uint32  value = 0;

    CTC_PTR_VALID_CHECK(p_value);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    switch (port_prop)
    {
        case CTC_PORT_PROP_MAC_EN:
        case CTC_PORT_PROP_AUTO_NEG_EN:
        case CTC_PORT_PROP_AUTO_NEG_MODE:
        case CTC_PORT_PROP_SPEED:
        case CTC_PORT_PROP_LINK_UP:
        case CTC_PORT_PROP_HALF_DUPLEX:
        case CTC_PORT_PROP_EEE_EN:
        case CTC_PORT_PROP_PREAMBLE:
        case CTC_PORT_PROP_IPG:
        case CTC_PORT_PROP_CHK_CRC_EN:
        case CTC_PORT_PROP_STRIP_CRC_EN:
        case CTC_PORT_PROP_APPEND_CRC_EN:
        case CTC_PORT_PROP_UNIDIR_EN:
        case CTC_PORT_PROP_LINK_INTRRUPT_EN:
            ret = _ctc_asw_mac_get_property(lchip, gport, port_prop, p_value);
            break;

        case CTC_PORT_PROP_VLAN_CTL:
            cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            value = GetIngressPort(V, noTagPkt_f, &ds);
            if (value)
            {
                *p_value = GetIngressPort(V, noUntagPkt_f, &ds) ? CTC_VLANCTL_DROP_ALL : CTC_VLANCTL_DROP_ALL_TAGGED;
            }
            else
            {
                *p_value = GetIngressPort(V, noUntagPkt_f, &ds) ? CTC_VLANCTL_DROP_ALL_UNTAGGED : CTC_VLANCTL_ALLOW_ALL_PACKETS;
            }
            break;
        case CTC_PORT_PROP_VLAN_DOMAIN:
            cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetIngressPort(V, stpidEnable_f, &ds) ? CTC_PORT_VLAN_DOMAIN_SVLAN : CTC_PORT_VLAN_DOMAIN_CVLAN;
            break;

        case CTC_PORT_PROP_LEARNING_EN:     /**< Set learning enable/disable on port */
            cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMacLkupCtrl(V,newEnable_f,&ds);
            break;

         case CTC_PORT_PROP_STATION_MOVE_ACTION:
            cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            value = GetMacLkupCtrl(V,moveToDrop_f,&ds);
            if (value == CTC_PORT_STATION_MOVE_ACTION_TYPE_FWD)
            {
                *p_value = CTC_PORT_STATION_MOVE_ACTION_TYPE_FWD;
            }
            else
            {
                value = GetMacLkupCtrl(V,moveToFifo_f,&ds);
                *p_value = value ? CTC_PORT_STATION_MOVE_ACTION_TYPE_DISCARD_TOCPU : CTC_PORT_STATION_MOVE_ACTION_TYPE_DISCARD;
            }
            break;

         case CTC_PORT_PROP_DEFAULT_VLAN:
             field = gport + CTC_VLAN_PORT_AD_BASE;
             cmd = DRV_IOR(IvmTable_t, DRV_ENTRY_FLAG);
             ret = DRV_IOCTL(lchip, field, cmd, &ds);
             *p_value = GetIvmTable(V, svid_f, &ds);
             break;

         case CTC_PORT_PROP_QOS_POLICY:
            cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            value = GetIngressPort(V,trustPriMode_f,&ds);
            if (value == 2)
            {
                *p_value = CTC_QOS_TRUST_STAG_COS;
            }
            else if (value == 3)
            {
                *p_value = CTC_QOS_TRUST_DSCP;
            }
            else
            {
                *p_value = CTC_QOS_TRUST_PORT;
            }
            break;

         case CTC_PORT_PROP_REPLACE_STAG_COS:
            cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            value = GetEgressPort(V,remarkScosMode_f,&ds);
            if(value == 2)
            {
                *p_value = 1;
            }
            else
            {
                *p_value = 0;
            }
            break;

        case CTC_PORT_PROP_DSCP_SELECT_MODE:
            cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetEgressPort(V,remarkDscpMode_f,&ds);
            break;

        case CTC_PORT_PROP_REPLACE_DSCP_EN:
            cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            value = GetEgressPort(V,remarkDscpMode_f,&ds);
            if(value == 2)
            {
                *p_value = 1;
            }
            else
            {
                *p_value = 0;
            }
            break;

        case CTC_PORT_PROP_DEFAULT_DSCP:
            cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetEgressPort(V,remarkDscp_f,&ds);
            break;

        case CTC_PORT_PROP_REPLACE_PCP_DEI:
            cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetEgressPort(V,remarkScosMode_f,&ds);
            break;

        case CTC_PORT_PROP_DEFAULT_PCP:
            cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            field = GetEgressPort(V,remarkScos_f,&ds);
            *p_value = (field >> 1);
            break;

         case CTC_PORT_PROP_DEFAULT_DEI:
            cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            field = GetEgressPort(V,remarkScos_f,&ds);
            *p_value = (field & 0x1);
            break;

        case CTC_PORT_PROP_MAX_FRAME_SIZE:
            cmd = DRV_IOR(MaxFrameLen_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetMaxFrameLen(V, len_f, &ds);
            break;

        case CTC_PORT_PROP_QOS_WRR_EN:
            cmd = DRV_IOR(SchPortMode_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetSchPortMode(V, wrrMode_f, &ds);
            break;

        case CTC_PORT_PROP_NEW_SA_DROP:
            cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = ((GetMacLkupCtrl(V, newsaToDrop_f, &ds) == 1)&&(GetMacLkupCtrl(V, newEnable_f, &ds) == 0))? 1:0;
            break;

        case CTC_PORT_PROP_PRIORITY_TAG_EN:
            cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
            ret = DRV_IOCTL(lchip, gport, cmd, &ds);
            *p_value = GetIngressPort(V, no1pPkt_f, &ds)?1:0;
            break;

        case CTC_PORT_PROP_PHY_INIT:
                ret = _ctc_asw_peri_get_phy_register_exist(lchip, gport);
                if (CTC_E_NOT_INIT == ret)
                {
                    *p_value = FALSE;
                    ret = CTC_E_NONE;
                }
                else
                {
                    *p_value = ret?FALSE:TRUE;
                }
                break;
            case CTC_PORT_PROP_PHY_EN:
                if (CTC_E_NONE == _ctc_asw_peri_get_phy_register_exist(lchip, gport))
                {
                    ret = _ctc_asw_peri_get_phy_prop(lchip, gport, CTC_PORT_PROP_PHY_EN, (void*)p_value);
                }
                else
                {
                    ret = _ctc_asw_mac_get_property(lchip, gport, CTC_PORT_PROP_MAC_EN, p_value);
                }
                break;
            case CTC_PORT_PROP_PHY_DUPLEX:
            case CTC_PORT_PROP_PHY_MEDIUM:
            case CTC_PORT_PROP_PHY_LOOPBACK:
            case CTC_PORT_PROP_PHY_AUTO_NEG_EN:
            case CTC_PORT_PROP_PHY_SPEED:
                if (CTC_E_NONE == _ctc_asw_peri_get_phy_register_exist(lchip, gport))
                {
                    ret = _ctc_asw_peri_get_phy_prop(lchip, gport, port_prop, (void*)p_value);
                }
                break;
        default:
            CTC_API_UNLOCK(lchip);
            return CTC_E_NOT_SUPPORT;
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief Set port property with direction

 @param[in] gport, global physical port

 @param[in] port_prop, port property

 @param[out] value

 @return CTC_E_XXX

*/
int32
ctc_asw_port_set_direction_property(uint8 lchip, uint32 gport, ctc_port_direction_property_t port_prop, ctc_direction_t dir, uint32 value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t ds;

    CTC_MAX_VALUE_CHECK(dir, CTC_BOTH_DIRECTION);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    if ((CTC_INGRESS == dir) || (CTC_BOTH_DIRECTION == dir))
    {
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        switch (port_prop)
        {
            case CTC_PORT_DIR_PROP_VLAN_FILTER_EN:
                SetIngressPort(V, bypassVlanCheck_f, &ds, !(value));
                break;
            case CTC_PORT_DIR_PROP_QOS_DOMAIN:
                CTC_MAX_VALUE_CHECK_UNLOCK(value, 7);
                SetIngressPort(V, priIndex_f, &ds, value);
                break;
            case CTC_PORT_DIR_PROP_PORT_POLICER_VALID:
                value = value ? 1 : 0;
                SetIngressPort(V, policeMode_f, &ds, value);
                SetIngressPort(V, counterEnable_f, &ds, value);
                break;
            default:
                CTC_API_UNLOCK(lchip);
                return CTC_E_INVALID_PARAM;
        }
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, gport, cmd, &ds));
    }
    if ((CTC_EGRESS == dir) || (CTC_BOTH_DIRECTION == dir))
    {
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        switch (port_prop)
        {
            case CTC_PORT_DIR_PROP_VLAN_FILTER_EN:
                SetEgressPort(V, bypassVlanCheck_f, &ds, !value);
                break;
            case CTC_PORT_DIR_PROP_QOS_DOMAIN:
                CTC_MAX_VALUE_CHECK_UNLOCK(value, 7);
                SetEgressPort(V, priIndex_f, &ds, value);
                break;
            default:
                ret =  CTC_E_NOT_SUPPORT;
        }
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, gport, cmd, &ds));
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief Get port property with direction

 @param[in] gport, global physical port

 @param[in] port_prop, port property

 @param[out] value

 @return CTC_E_XXX

*/
int32
ctc_asw_port_get_direction_property(uint8 lchip, uint32 gport, ctc_port_direction_property_t port_prop, ctc_direction_t dir, uint32* p_value)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t ds;

    CTC_MAX_VALUE_CHECK(dir, CTC_BOTH_DIRECTION - 1);
    CTC_PTR_VALID_CHECK(p_value);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    if (CTC_INGRESS == dir)
    {
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        switch (port_prop)
        {
            case CTC_PORT_DIR_PROP_VLAN_FILTER_EN:
                *p_value = !GetIngressPort(V, bypassVlanCheck_f, &ds);
                break;
            case CTC_PORT_DIR_PROP_QOS_DOMAIN:
                *p_value = GetIngressPort(V, priIndex_f, &ds);
                break;
            case CTC_PORT_DIR_PROP_PORT_POLICER_VALID:
                *p_value = GetIngressPort(V, policeMode_f, &ds);
                break;
            default :
                ret = CTC_E_INVALID_PARAM;
                break;
        }
    }
    else if (CTC_EGRESS == dir)
    {
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, gport, cmd, &ds);
        switch (port_prop)
        {
            case CTC_PORT_DIR_PROP_VLAN_FILTER_EN :
                *p_value = !GetEgressPort(V, bypassVlanCheck_f, &ds);
                break;
            case CTC_PORT_DIR_PROP_QOS_DOMAIN:
                *p_value = GetEgressPort(V, priIndex_f, &ds);
                break;
            default:
                ret = CTC_E_NOT_SUPPORT;
                break;
        }
    }
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_port_set_vlan_range(uint8 lchip, uint32 gport, ctc_vlan_range_info_t* vrange_info, bool enable)
{
    int32  ret = 0;
    uint32 cmd = 0;
    bool is_svlan = TRUE;
    VlanPortCtrl_m vlan_port_ctl;

    CTC_PTR_VALID_CHECK(vrange_info);
    CTC_MAX_GPORT_CHECK(gport);

    sal_memset(&vlan_port_ctl, 0, sizeof(vlan_port_ctl));

    CTC_API_LOCK(lchip);
    ret = _ctc_asw_vlan_get_internal_range_type(lchip, vrange_info, &is_svlan);
    cmd = DRV_IOR(VlanPortCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &vlan_port_ctl);
    SetVlanPortCtrl(V, vrangeIdx_f, &vlan_port_ctl, vrange_info->vrange_grpid);
    SetVlanPortCtrl(V, vrangeEn_f, &vlan_port_ctl, (enable) ? 1 : 0);
    SetVlanPortCtrl(V, rangeVidMode_f, &vlan_port_ctl, (is_svlan) ? 1:2 );
    cmd = DRV_IOW(VlanPortCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &vlan_port_ctl);
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_get_vlan_range(uint8 lchip, uint32 gport, ctc_vlan_range_info_t* vrange_info, bool* enable)
{
    int32  ret = 0;
    uint32 cmd = 0;
    VlanPortCtrl_m vlan_port_ctl;

    CTC_PTR_VALID_CHECK(vrange_info);
    CTC_PTR_VALID_CHECK(enable);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(VlanPortCtrl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, gport, cmd, &vlan_port_ctl);
    vrange_info->vrange_grpid = GetVlanPortCtrl(V, vrangeIdx_f, &vlan_port_ctl);
    *enable = GetVlanPortCtrl(V, vrangeEn_f, &vlan_port_ctl);
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_set_scl_property(uint8 lchip, uint32 gport, ctc_port_scl_property_t* prop)
{
    int32  ret = 0;
    uint32 cmd = 0;
    uint8 hash_type = 0;
    ds_t ds;

    CTC_PTR_VALID_CHECK(prop);
    CTC_MAX_GPORT_CHECK(gport);
    if (prop->direction)
    {
        return CTC_E_NOT_SUPPORT;
    }

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, gport, cmd, &ds);
    SetIngressPort(V, ivmXEn_f, &ds, (prop->tcam_type) ? 1 : 0);
    SetIngressPort(V, ivmMode_f, &ds, (prop->tcam_type) ? 0x3:0x0);
    cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);

    switch (prop->hash_type)
    {
        case CTC_PORT_IGS_SCL_HASH_TYPE_MAC_SA :
            hash_type = 0x1;
            break;
        case CTC_PORT_IGS_SCL_HASH_TYPE_PORT_IP_SA :
            hash_type = 0x2;    /* same as 0x0a*/
            break;
        case CTC_PORT_IGS_SCL_HASH_TYPE_IP_SA :
            hash_type = 0x3;    /* same as 0x09*/
            break;
        case CTC_PORT_IGS_SCL_HASH_TYPE_PORT_SVLAN :
            hash_type = 0x4;
            break;
        case CTC_PORT_IGS_SCL_HASH_TYPE_PORT_2VLAN :
            hash_type = 0x5;
            break;
        case CTC_PORT_IGS_SCL_HASH_TYPE_PORT_CVLAN :
            hash_type = 0x6;
            break;
        case CTC_PORT_IGS_SCL_HASH_TYPE_PORT_SVLAN_COS:
            hash_type = 0x7;
            break;
        case CTC_PORT_IGS_SCL_HASH_TYPE_PORT_CVLAN_COS:
            hash_type = 0x8;
            break;
        default :
            hash_type = 0xf;
            break;
    }
    cmd = DRV_IOR(VlanPortCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
    if (!prop->scl_id)
    {
        SetVlanPortCtrl(V, keyType1_f, &ds, hash_type);
    }
    else
    {
        SetVlanPortCtrl(V, keyType2_f, &ds, hash_type);
    }
    cmd = DRV_IOW(VlanPortCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_get_scl_property(uint8 lchip, uint32 gport, ctc_port_scl_property_t* prop)
{
    int32  ret = 0;
    uint32 cmd = 0;
    uint8 hash_type = 0xf;
    ds_t ds;

    CTC_PTR_VALID_CHECK(prop);
    CTC_MAX_GPORT_CHECK(gport);
    if (prop->direction)
    {
        return CTC_E_NOT_SUPPORT;
    }

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, gport, cmd, &ds);
    prop->tcam_type = GetIngressPort(V, ivmXEn_f, &ds);

    cmd = DRV_IOR(VlanPortCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &ds);
    if (!prop->scl_id)
    {
        hash_type = GetVlanPortCtrl(V, keyType1_f, &ds);
    }
    else
    {
        hash_type = GetVlanPortCtrl(V, keyType2_f, &ds);
    }
    switch (hash_type)
    {
        case  0x1 :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_MAC_SA;
            break;
        case  0x2 :
        case  0xa :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_IP_SA;
            break;
        case  0x3 :
        case  0x9 :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_IP_SA;
            break;
        case  0x4 :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_SVLAN;
            break;
        case  0x5 :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_2VLAN;
            break;
        case  0x6 :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_CVLAN;
            break;
        case  0x7 :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_SVLAN_COS;
            break;
        case  0x8 :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_PORT_CVLAN_COS;
            break;
        default :
            prop->hash_type = CTC_PORT_IGS_SCL_HASH_TYPE_DISABLE;
            break;
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32 ctc_asw_port_set_interface_mode(uint8 lchip, uint32 gport, ctc_port_if_mode_t* if_mode)
{
    int32  ret = 0;
    uint32 cmd = 0;
    uint8 speed = 0;
    uint8 if_type = 0;
    uint8 port_en = 0;
    ctc_chip_serdes_mode_t serdes_mode;
    ctc_chip_serdes_mode_t old_serdes_mode;
    MacTxCtrl_m mac_tx_ctrl;

    CTC_PTR_VALID_CHECK(if_mode);
    CTC_MAX_GPORT_CHECK(gport);

    switch(if_mode->speed)
    {
        case CTC_PORT_SPEED_1G:
            speed = 2;
            break;
        case CTC_PORT_SPEED_100M :
            speed = 1;
            break;
        case CTC_PORT_SPEED_10M :
            speed = 0;
            break;
        default:
            return CTC_E_INVALID_PARAM;
            break;
    }

    switch(if_mode->interface_type)
    {
        case CTC_PORT_IF_SGMII:
            if_type = 6;
            serdes_mode = CTC_CHIP_SERDES_SGMII_MODE;
            break;
        case CTC_PORT_IF_QSGMII:
            serdes_mode = CTC_CHIP_SERDES_QSGMII_MODE;
            if_type = 6;
            break;
        case CTC_PORT_IF_FX:
            if_type = 6;
            serdes_mode = CTC_CHIP_SERDES_100BASEFX_MODE;
            break;
        case CTC_PORT_IF_PHY:
             if_type = 1;
             serdes_mode = CTC_CHIP_SERDES_PHY_MODE;
        default:
            return CTC_E_INVALID_PARAM;
            break;
    }

    CTC_API_LOCK(lchip);
    ret = _ctc_asw_datapath_get_pcs_type(lchip, gport, &old_serdes_mode);
    if (old_serdes_mode != serdes_mode)
    {
        ret = ret?ret:_ctc_asw_datapath_set_pcs_type(lchip, gport, serdes_mode);
    }
    cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
    ret = ret?ret: DRV_IOCTL(lchip, gport, cmd, &mac_tx_ctrl);
    port_en=GetMacTxCtrl(V, portEn_f, &mac_tx_ctrl);
    if(port_en)
    {
        SetMacTxCtrl(V, portEn_f, &mac_tx_ctrl, 0);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &mac_tx_ctrl);
    }

    SetMacTxCtrl(V, speedSel_f, &mac_tx_ctrl, speed);
    SetMacTxCtrl(V, intfType_f, &mac_tx_ctrl, if_type);
    if (port_en)
    {
        SetMacTxCtrl(V, portEn_f, &mac_tx_ctrl, 1);
    }
    cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &mac_tx_ctrl);
    CTC_API_UNLOCK(lchip);

    return ret;
}

/**
 @brief Set flow control of port

 @param[in] Point to flow control property

 @remark  Enable/disable flow control or priority flow control

 @return CTC_E_XXX

*/
int32
ctc_asw_port_set_flow_ctl_en(uint8 lchip, ctc_port_fc_prop_t *p_fc_prop)
{
    int32  ret = 0;
    uint32 cmd = 0;
    MacRxCtrl_m mac_rx_ctrl;
    MacTxCtrl_m mac_tx_ctrl;

    CTC_PTR_VALID_CHECK(p_fc_prop);
    CTC_MAX_GPORT_CHECK(p_fc_prop->gport);
    CTC_API_LOCK(lchip);
    if ((CTC_EGRESS == p_fc_prop->dir) || (CTC_BOTH_DIRECTION == p_fc_prop->dir))
    {
        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, p_fc_prop->gport, cmd, &mac_tx_ctrl);
        SetMacTxCtrl(V, flowControlEn_f, &mac_tx_ctrl, p_fc_prop->enable);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, p_fc_prop->gport, cmd, &mac_tx_ctrl);
    }
    if ((CTC_INGRESS== p_fc_prop->dir) || (CTC_BOTH_DIRECTION == p_fc_prop->dir))
    {
        cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, p_fc_prop->gport, cmd, &mac_rx_ctrl);
        SetMacRxCtrl(V, flowControlEn_f, &mac_rx_ctrl, p_fc_prop->enable);
        cmd = DRV_IOW(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, p_fc_prop->gport, cmd, &mac_rx_ctrl);
    }

    CTC_API_UNLOCK(lchip);
    return ret;
}

/**
 @brief Get flow control of port

 @param[in|out] Point to flow control property

 @remark  Get flow control or priority flow control enable/disable

 @return CTC_E_XXX

*/
int32
ctc_asw_port_get_flow_ctl_en(uint8 lchip, ctc_port_fc_prop_t *p_fc_prop)
{
    int32  ret = 0;
    uint32 cmd = 0;
    MacRxCtrl_m mac_rx_ctrl;
    MacTxCtrl_m mac_tx_ctrl;
    CTC_PTR_VALID_CHECK(p_fc_prop);
    CTC_MAX_GPORT_CHECK(p_fc_prop->gport);
    CTC_API_LOCK(lchip);
    if (CTC_EGRESS == p_fc_prop->dir)
    {
        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, p_fc_prop->gport, cmd, &mac_tx_ctrl);
        p_fc_prop->enable = GetMacTxCtrl(V, flowControlEn_f, &mac_tx_ctrl);
    }
    if (CTC_INGRESS == p_fc_prop->dir)
    {
        cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip, p_fc_prop->gport, cmd, &mac_rx_ctrl);
        p_fc_prop->enable = GetMacRxCtrl(V, flowControlEn_f, &mac_rx_ctrl);
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

static int32
_ctc_asw_port_acl_map_type(uint8 lchip, uint8 key_type, uint8* p_out_key_type, uint8 is_hw)
{
    uint8 hw_key_type[] = {CTC_ACL_KEY_MAC, CTC_ACL_KEY_MAC_EXT, CTC_ACL_KEY_IPV4, CTC_ACL_KEY_MAC_IPV4,
                           CTC_ACL_KEY_IPV4_EXT, CTC_ACL_KEY_MAC_IPV6, CTC_ACL_KEY_IPV6, CTC_ACL_KEY_IPV6_EXT,
                           CTC_ACL_KEY_UDF};
    if (0 == is_hw)
    {
        switch(key_type)
        {
            case CTC_ACL_KEY_MAC:
                *p_out_key_type = 0;
                break;
            case CTC_ACL_KEY_MAC_EXT:
                *p_out_key_type = 1;
                break;
            case CTC_ACL_KEY_IPV4:
                *p_out_key_type = 2;
                break;
            case CTC_ACL_KEY_MAC_IPV4:
                *p_out_key_type = 3;
                break;
            case CTC_ACL_KEY_IPV4_EXT:
                *p_out_key_type = 4;
                break;
            case CTC_ACL_KEY_MAC_IPV6:
                *p_out_key_type = 5;
                break;
            case CTC_ACL_KEY_IPV6:
                *p_out_key_type = 6;
                break;
            case CTC_ACL_KEY_IPV6_EXT:
                *p_out_key_type = 7;
                break;
            case CTC_ACL_KEY_UDF:
                *p_out_key_type = 8;
                break;
            default:
                return CTC_E_INVALID_PARAM;
                break;
        }
    }
    else
    {
       *p_out_key_type = hw_key_type[key_type];
    }
    
    return CTC_E_NONE;
}

int32
_ctc_asw_port_set_acl_property(uint8 lchip, uint32 gport, ctc_acl_property_t* p_prop, uint8 is_inner)
{
    int32  ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint8 key_type = 0;
    uint16 range_en_bmp = 0;
    ds_t data = {0};

    CTC_ERROR_RETURN(_ctc_asw_port_acl_map_type(lchip, p_prop->tcam_lkup_type, &key_type, 0));
    cmd = DRV_IOR(AclPortKeyConfig_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, gport, cmd, &data);
    
    range_en_bmp = GetAclPortKeyConfig(V, keyRangeEn_f, &data);
    (CTC_FLAG_ISSET(p_prop->flag, CTC_ACL_PROP_FLAG_USE_L4_PORT_RANGE)) ? CTC_BIT_SET(range_en_bmp, key_type) : CTC_BIT_UNSET(range_en_bmp,  key_type) ;

    SetAclPortKeyConfig(V, keyRangeEn_f, &data, range_en_bmp);
    SetAclPortKeyConfig(V, aclEn_f, &data, p_prop->acl_en);
    if (p_prop->acl_priority > 0 && is_inner)
    {
        SetAclPortKeyConfig(V, slice0KeyMode_f - p_prop->acl_priority + 1 , &data, key_type);
    }
    else
    {
        uint8 acl_slice_id = 0;
        uint8 first_slice_id = 0;

        ret = ret? ret : _ctc_asw_chip_get_first_slice(lchip, &first_slice_id);
        if (p_prop->acl_priority == 0)
        {
            for (acl_slice_id = 0; acl_slice_id < first_slice_id; acl_slice_id++)
            {
                SetAclPortKeyConfig(V, slice0KeyMode_f - acl_slice_id, &data, key_type);
            }
        }
        else if(p_prop->acl_priority && first_slice_id > (p_prop->acl_priority*2+1))
        {
            SetAclPortKeyConfig(V, slice0KeyMode_f - p_prop->acl_priority*2, &data, key_type);
            SetAclPortKeyConfig(V, slice0KeyMode_f - (p_prop->acl_priority*2+1), &data, key_type);
        }
        else if(p_prop->acl_priority)
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    SetAclPortKeyConfig(V, vidSel_f, &data, (CTC_FLAG_ISSET(p_prop->flag, CTC_ACL_PROP_FLAG_USE_CVLAN_RANGE)) ? 1 : 0);
    /*SetAclPortKeyConfig(V, bitmapMode_f, &data, (CTC_FLAG_ISSET(p_prop->flag, CTC_ACL_PROP_FLAG_USE_LOGIC_PORT) ? 1 : 0));*/
    cmd = DRV_IOW(AclPortKeyConfig_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &data);

#if 0
    cmd = DRV_IOR(UdfPortCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &udf_port_cfg);
    SetUdfPortCtrl(V, bitmapMode_f, &udf_port_cfg, (CTC_FLAG_ISSET(p_prop->flag, CTC_ACL_PROP_FLAG_USE_LOGIC_PORT) ? 1 : 0));
    cmd = DRV_IOW(UdfPortCtrl_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &udf_port_cfg);
#endif

    return ret;
}

int32
ctc_asw_port_set_acl_property(uint8 lchip, uint32 gport, ctc_acl_property_t* p_prop)
{
    int32  ret = CTC_E_NONE;
    CTC_PTR_VALID_CHECK(p_prop);
    CTC_MAX_GPORT_CHECK(gport);
    CTC_MAX_VALUE_CHECK(p_prop->acl_priority, 4);
    
    CTC_API_LOCK(lchip);
    ret = _ctc_asw_port_set_acl_property(lchip, gport, p_prop, 0);
    CTC_API_UNLOCK(lchip);
    return ret ;
}

int32
ctc_asw_port_get_acl_property(uint8 lchip, uint32 gport, ctc_acl_property_t* p_prop)
{
    int32  ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t data = {0};
    uint8 key_type = 0;
    uint16 range_en_bmp = 0;

    CTC_PTR_VALID_CHECK(p_prop);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(AclPortKeyConfig_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, gport, cmd, &data);
    p_prop->acl_en = GetAclPortKeyConfig(V, aclEn_f, &data);
    key_type = GetAclPortKeyConfig(V, slice0KeyMode_f - p_prop->acl_priority * 2, &data);
    ret = ret?ret:_ctc_asw_port_acl_map_type(lchip, key_type, &p_prop->tcam_lkup_type, 1);

    range_en_bmp = GetAclPortKeyConfig(V, keyRangeEn_f, &data);
    if (CTC_IS_BIT_SET(range_en_bmp, key_type))
    {
        p_prop->flag |= CTC_ACL_PROP_FLAG_USE_L4_PORT_RANGE;
        if(GetAclPortKeyConfig(V, vidSel_f, &data))
        {
            p_prop->flag |= CTC_ACL_PROP_FLAG_USE_CVLAN_RANGE;
        }
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_get_mac_link_up(uint8 lchip, uint32 gport, bool* is_up)
{
    int32 ret = CTC_E_NONE;
    uint32 link_status = 0;

    CTC_PTR_VALID_CHECK(is_up);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    ret = _ctc_asw_datapath_get_link_up(lchip, gport, &link_status);
    *is_up = (link_status)?TRUE:FALSE;
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_set_phy_property(uint8 lchip, uint32 gport, ctc_port_property_t port_prop, void* p_value)
{
    int32 ret = CTC_E_NONE;

    CTC_PTR_VALID_CHECK(p_value);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    ret = _ctc_asw_peri_set_phy_prop(lchip, gport, port_prop, p_value);
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_get_phy_property(uint8 lchip, uint32 gport, ctc_port_property_t port_prop, void* p_value)
{
    int32 ret = CTC_E_NONE;

    CTC_PTR_VALID_CHECK(p_value);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    ret = _ctc_asw_peri_get_phy_prop(lchip, gport, port_prop, p_value);
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_set_restriction(uint8 lchip, uint32 gport, ctc_port_restriction_t* p_restriction)
{
    int32  ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t data = {0};
    uint32 value = 0;
    
    CTC_PTR_VALID_CHECK(p_restriction);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, gport, cmd, &data);

    value = CTC_FLAG_ISSET(p_restriction->type, CTC_PORT_BLOCKING_UNKNOW_UCAST) ? 1 : 0;
    SetEgressPort(V, blockUlfFlooding_f, &data, value);

    value = CTC_FLAG_ISSET(p_restriction->type, CTC_PORT_BLOCKING_UNKNOW_MCAST) ? 1 : 0;
    SetEgressPort(V, blockMlfFlooding_f, &data, value);

    value = CTC_FLAG_ISSET(p_restriction->type, CTC_PORT_BLOCKING_BCAST) ? 1 : 0;
    SetEgressPort(V, blockBcFlooding_f, &data, value);

    cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : DRV_IOCTL(lchip, gport, cmd, &data);
    
    CTC_API_UNLOCK(lchip);
    return ret;

}


int32
ctc_asw_port_get_restriction(uint8 lchip, uint32 gport, ctc_port_restriction_t* p_restriction)
{
    int32  ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t data = {0};
    uint32 value = 0;

    CTC_PTR_VALID_CHECK(p_restriction);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, gport, cmd, &data);

    value = GetEgressPort(V, blockUlfFlooding_f, &data);
    if (value)
    {
        CTC_SET_FLAG(p_restriction->type, CTC_PORT_BLOCKING_UNKNOW_UCAST);
    }

    value = GetEgressPort(V, blockMlfFlooding_f, &data);
    if (value)
    {
        CTC_SET_FLAG(p_restriction->type, CTC_PORT_BLOCKING_UNKNOW_MCAST);
    }

    value = GetEgressPort(V, blockBcFlooding_f, &data);
    if (value)
    {
        CTC_SET_FLAG(p_restriction->type, CTC_PORT_BLOCKING_BCAST);
    }
    CTC_API_UNLOCK(lchip);

    return ret;
}

int32
ctc_asw_port_init(uint8 lchip, void* p_port_global_cfg)
{
    int32 ret = 0;
    uint32 cmd = 0;
    uint32 i = 0;
    uint16 ivm_index = 0;
    ds_t data = {0};

    /*tpid*/
    for (i = 0; i < CTC_ASW_MAX_PORT_NUM_PER_CHIP; i++)
    {
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, i, cmd, &data));
        SetIngressPort(V, stpidEnable_f, &data, 0x1);/*recognize 1 tag*/
        SetIngressPort(V, ctpidEnable_f, &data, 0x1);/*recognize 1 tag*/
        SetIngressPort(V, bypassVlanCheck_f, &data, 0x1);
        cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, i, cmd, &data));
        cmd = DRV_IOR(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, i, cmd, &data));
        SetEgressPort(V,stpidIndex_f,&data,0x0);
        SetEgressPort(V,ctpidIndex_f,&data,0x0);
        SetEgressPort(V, portTpidEnable_f, &data, 0x1);
        SetEgressPort(V, bypassVlanCheck_f, &data, 0x1);
        SetEgressPort(V, portDown_f, &data, 0x1);
        cmd = DRV_IOW(EgressPort_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : (DRV_IOCTL(lchip, i, cmd, &data));
        /*mac filter default enable */
        cmd = DRV_IOR(MacLkupCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret :DRV_IOCTL(lchip, i, cmd, &data);
        SetMacLkupCtrl(V,smacFilter_f,&data,1);
        SetMacLkupCtrl(V,dmacFilter_f,&data,1);
        /*macda hit pending entry default flooding */
        SetMacLkupCtrl(V,newLearnPending_f,&data,1);
        /*macda hit move entry default flooding */
        SetMacLkupCtrl(V,stationMovePending_f,&data,1);
        /*default ip based l2mc enable*/
        SetMacLkupCtrl(V,ipmcEnable_f,&data,1);
        cmd = DRV_IOW(MacLkupCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, i, cmd, &data);
        sal_memset(&data, 0, sizeof(ds_t));
        ivm_index = i + CTC_VLAN_PORT_AD_BASE;    /*ivm_table 269~298 used for port(total 29)*/
        SetPort2vlan(V, ivmIndex_f, &data, ivm_index);
        cmd = DRV_IOW(Port2vlan_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, i, cmd, &data);
        sal_memset(&data, 0, sizeof(ds_t));
        SetIvmTable(V, valid_f, &data, 1);
        SetIvmTable(V, svid_f, &data, 1);
        cmd = DRV_IOW(IvmTable_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, ivm_index, cmd, &data);
        sal_memset(&data, 0, sizeof(ds_t));
        SetVlanPortCtrl(V, keyType1_f, &data, 0xf);
        SetVlanPortCtrl(V, keyType2_f, &data, 0xf);
        cmd = DRV_IOW(VlanPortCtrl_t, DRV_ENTRY_FLAG);
        ret = ret ? ret : DRV_IOCTL(lchip, i, cmd, &data);

        /*mac init*/
        sal_memset(&data, 0, sizeof(ds_t));
        cmd = DRV_IOR(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, i, cmd, &data);
        SetMacRxCtrl(V, crcStripEn_f, &data, 1);
        SetMacRxCtrl(V, crcCheckEn_f, &data, 1);
        SetMacRxCtrl(V, minFrameLen_f, &data, 0);
        SetMacRxCtrl(V, preCheckEn_f, &data, 1);
        cmd = DRV_IOW(MacRxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret? ret:DRV_IOCTL(lchip, i, cmd, &data);

        sal_memset(&data, 0, sizeof(ds_t));
        cmd = DRV_IOR(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret?ret:DRV_IOCTL(lchip, i, cmd, &data);
        SetMacTxCtrl(V, crcInsertEn_f, &data, 1);
        SetMacTxCtrl(V, speedSel_f, &data, 2);
        SetMacTxCtrl(V, intfType_f, &data, (i<CTC_ASW_INTERNAL_PHY_PORT_NUM)?1:6);
        cmd = DRV_IOW(MacTxCtrl_t, DRV_ENTRY_FLAG);
        ret = ret?ret:DRV_IOCTL(lchip, i, cmd, &data);
    }

    /* callback func for software learning */
    ret = ret? ret: _ctc_asw_intr_register_cb_func(lchip, CTC_ASW_CB_PCS_LINK,
        _ctc_asw_port_pcs_link_isr);
    return ret;
}

int32
ctc_asw_port_deinit(uint8 lchip)
{
    return CTC_E_NONE;
}
